package com.itstyle.seckill.distributedlock.zookeeper;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Test;
/**
 * 基于curator的zookeeper分布式锁
 * 这里我们开启5个线程，每个线程获取锁的最大等待时间为5秒，为了模拟具体业务场景，方法中设置4秒等待时间。
 * 开始执行main方法，通过ZooInspector监控/curator/lock下的节点如下图：
 */
public class CuratorUtil {
    private static String address = "127.0.0.1:2181";
    
    @Test
    public void testZK() {
		//1、重试策略：初试时间为1s 重试3次
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1); 
		//2、通过工厂创建连接
		CuratorFramework client = CuratorFrameworkFactory.newClient(address, retryPolicy);
        //3、开启连接
        client.start();
        try {
			client.create().creatingParentsIfNeeded().forPath("/curator/seckill", "I'm a service".getBytes());
        	client.delete().deletingChildrenIfNeeded().forPath("/curator/lock");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			client.close();
		}
    }
	
    public static void main(String[] args) {
		//1、重试策略：初试时间为1s 重试3次
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1); 
		//2、通过工厂创建连接
		CuratorFramework client = CuratorFrameworkFactory.newClient(address, retryPolicy);
        //3、开启连接
        client.start();
        //4 分布式锁
        final InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock"); 
//        InterProcessMutex mutex2 = new InterProcessMutex(client, "/curator/lock"); 
//        try {
//            mutex.acquire();
//			mutex2.acquire();
//		} catch (Exception e1) {
//			// TODO Auto-generated catch block
//			e1.printStackTrace();
//			System.out.println("error");
//		}
        //读写锁
        //InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/readwriter");

        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
        
        for (int i = 0; i < 5; i++) {
        	int j = i;
            fixedThreadPool.submit(() -> {
            	boolean flag = false;
            	while (!flag) {
            		Thread currentThread = Thread.currentThread();
	            	try {
	            		//尝试获取锁，最多等待5秒
	            		flag = mutex.acquire(5, TimeUnit.SECONDS);
	            		if(flag){
	            			System.out.println("线程"+currentThread.getId()+"获取锁成功");
	            		}else{
	            			System.out.println("线程"+currentThread.getId()+"获取锁失败");
	            		}
	            		//模拟业务逻辑，延时4秒
	            		Thread.sleep(4000);
					} catch (Exception e) {
						e.printStackTrace();
					} finally{
						if(flag){
							try {
								mutex.release();
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
//				        client.close();
					}
            	}
            });
        }
	}
}
